package com.lql.integrated.util;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;

/**
 * @author wangjian
 * @date 2019/10/9
 * APP登录Token的生成和解析
 */
@Log4j2
@ConfigurationProperties(prefix = "jwt")
@Component
@Data
public class JwtUtil {

    /**
     * JWT时间默认盐值 666666
     */
    private String calendarSalt = "666666";
    /**
     * JWT时间默认单位 分钟
     */
    private static final int CALENDAR_FIELD = Calendar.MINUTE;
    /**
     * JWT时间默认长度
     */
    private int calendarInterval = 1000;
    /**
     * JWT时间默认名称
     */
    private String jwtUserName = "username";

    /**
     * JWT生成Token.<br/>
     * <p>
     * JWT构成: header, payload, signature
     *
     * @param username 登录成功后用户user_id, 参数user_id不可传空
     */
    public String createToken(String username, String salt) {
        try {
            if (ObjectUtil.isEmpty(username)) {
                log.error(jwtUserName);
                return null;
            }
            log.debug(jwtUserName+":{}", username);
            // 如果盐值为空，则使用默认值：666666
            if (ObjectUtil.isEmpty(salt)) {
                salt = calendarSalt;
            }
            log.debug("salt:{}", salt);
            Calendar nowTime = Calendar.getInstance();
            nowTime.add(CALENDAR_FIELD, calendarInterval);
            Date expiresDate = nowTime.getTime();
            log.debug("expireDate:{}", expiresDate);
            // 生成token
            Algorithm algorithm = Algorithm.HMAC256(salt);
            return JWT.create()
                    .withClaim(jwtUserName, username)
                    .withIssuedAt(DateTime.now())
                    .withExpiresAt(expiresDate)
                    .sign(algorithm);
        } catch (Exception e) {
            log.error("generateToken exception", e);
        }
        return null;
    }

    public boolean verifyToken(String token, String salt) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(salt);
            JWTVerifier verifier = JWT.require(algorithm)
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (Exception e) {
            log.error("Verify Token Exception", e);
        }
        return false;
    }

    /**
     * 解析token，获取token数据
     *
     * @param token
     * @return
     */
    public DecodedJWT getJwtInfo(String token) {
        return JWT.decode(token);
    }


    /**
     * 获取usernames
     *
     * @param token
     * @return
     */
    public String getUsername(String token) {
        if (ObjectUtil.isEmpty(token)) {
            return null;
        }
        DecodedJWT decodedJWT = getJwtInfo(token);
        return decodedJWT.getClaim(jwtUserName).asString();
    }

    /**
     * 获取创建时间
     *
     * @param token
     * @return
     */
    public Date getIssuedAt(String token) {
        DecodedJWT decodedJWT = getJwtInfo(token);
        return decodedJWT.getIssuedAt();
    }

    /**
     * 获取过期时间
     *
     * @param token
     * @return
     */
    public Date getExpireDate(String token) {
        DecodedJWT decodedJWT = getJwtInfo(token);
        return decodedJWT.getExpiresAt();
    }

    /**
     * 判断token是否已过期
     *
     * @param token
     * @return
     */
    public boolean isExpired(String token) {
        Date expireDate = getExpireDate(token);
        if (expireDate == null) {
            return true;
        }
        return expireDate.before(DateTime.now());
    }

}
